#pragma once
#include "../common/net.hpp"
#include "../common/message.hpp"


// 服务端有三个主要组件，共同工作来处理客户端的请求：

// ServiceDescribe（服务描述）：
// 1.描述一个具体的服务（比如"加法服务"、"查询用户服务"等）
// 2.定义这个服务需要什么参数，返回什么类型的结果
// 3.包含实际执行服务的函数

// ServiceManager（服务管理器）：
// 1.管理所有可用的服务
// 2.当请求到达时，根据请求中的方法名找到对应的服务

// RpcRouter（RPC路由器）：
// 1.接收所有客户端请求
// 2.使用ServiceManager找到对应的服务
// 3.调用服务处理请求
// 4.将结果返回给客户端

namespace bitrpc{
    //命令空间：避免重命名冲突
    namespace server{    
        //对象：数据类型
        enum class VType{
            BOOL = 0,
            INTEGRAL,
            NUMERIC,
            STRING,
            ARRAY,
            OBJECT
        };
//ServiceDescribe：服务描述主要负责描述一个RPC服务的元信息和行为
        class ServiceDescribe{
            public:
                using ptr = std::shared_ptr<ServiceDescribe>;
                using ServiceCallback = std::function<void(const Json::Value&, const Json::Value&)>;    //服务回调函数：[Json::Value 对象，Json::Value result返回结果]
                using ParamsDescribe = std::pair<std::string, VType>                                    //对象描述：[对象方法，对象数据类型]

                ServiceDescribe(std::string &&mnane, std::vector<ParamsDescribe> &&desc,
                    vtype vtype, ServiceCallback &&handler):
                    _method_name(std::move(mname),_callback(std::move(handler)),
                    _params_desc(std::move(desc)), _return_type(vtype)){}

                const std::string &method(){ return _mothod_name; }                                   

                // 收到请求对象，进行参数校验:1.参数字段是否存在 2.类型是否一致
                bool paramCheck(const Json::Value &params){
                    for(auto &desc : _params_desc){                                         //同全部对象遍历比较：std::vector<ParamsDescribe> _params_desc; 
                        if(params.isMember(desc.first) == false){                           //params是否存在该对象名称
                            ELOG("参数字段完整性校验失败! %s 字段缺失", desc.first.c_str());
                            return false;
                        }
                        if(check(desc.second, params[desc.first] == false)){                //[desc.对象类型，对象[对象名称KEY值]]
                            ELOG("%s 参数类型校验失败!", desc.first.c_str());
                            return false;
                        }
                    }
                    return true;
                }

                //设置该服务对应的回调函数
                bool call(const Json::Value &params, Json::Value &result){
                    _callback(params, result);
                    if(rtypeCheck(result) == false){    //检查该结果
                        ELOG("回调处理函数中的响应信息校验失败!");
                        return false;
                    }
                    return true;
                }
            private:
                //简化外部检测操作，传递对象调用check接口
                bool rtypeCheck(const Json::Value &val){
                    return check(_return_type, val);
                }

                //检查类型对应对象的类型
                bool check(VType vtype, const Json::Value &val){
                //通过"类型"判断对象返回值是否这个结果
                    switch(vtype){
                        case VType::BOOL : return val.isBool();
                        case VType::INTEGRAL : return val.isIntegral();
                        case VType::NUMERIC : return val.isNumeric();
                        case VType::STRING : return val.isString();
                        case VType::ARRAY : return val.isArray();
                        case VType::OBJECT : return val.isObject();
                    }
                    //不存在该类型
                    return false;
                }
            private:
                std::string _mothod_name;                       //方法名称
                ServiceCallback _callback;                      //实际的业务回调函数，提供外部调用，设置回调函数并且调用回调函数
                std::vector<ParamsDescribe> _params_desc;       //参数字段格式描述，存储多个对象：[对象方法，对象数据类型]......
                VType _return_type;                             //结果作为"返回值"类型的描述
        };

        //建造者模式，提前初始化"ServiceDescribe"类相关数据
        class SDescribeFactory{
            public:
                void serMethodName(const std::string &name){
                    _method_name = name;
                }
                void setReturnType(VType vtype){                    
                    _return_type = vtype;
                }
                void setParamsDesc(const std::string &pname, VType vtype){
                    _params_desc.push_back(ServiceDescribe::ParamsDescribe(pname,vtype));   //插入可调用对象
                }
                void setCallback(const ServiceDescribe::ServiceCallback &cb){               //设置可调用的回调函数
                    _callback = cb;
                }

            //建造者
            SDescribeFactory::ptr build(){
                return std::make_shared<ServiceDescribe>(std::move(_mothod_name),std::move(_callback),
                        std::move(_params_desc), std::Move(_return_type));
            }
            //辅助初始化"ServiceDescribe"内部数值
            private:
            std::string _mothod_name;                 //方法名称
            ServiceCallback _callback;                //实际的业务回调函数
            std::vector<ParamsDescribe> _params_desc; //参数字段格式描述，存储多个"ParamsDescribe"服务描述
            VType _return_type;                       //结果作为返回值类型的描述
        };
        
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //ServiceManager：负责管理所有注册的服务，当收到RPC请求时，可以根据方法名快速找到对应的服务处理函数       
//unordered_map容器:负责管理"ServiceDescribe"对象，以"method_name"为key找到对应的对象
        class ServiceManager{
            public:
                using ptr = std::shared_ptr<ServiceManager>;

                //1.插入
                void insert(const ServiceDescribe::ptr &desc){
                    std::unique_lock<mutex> lock(_mutex);
                    _services.insert(std::make_pair(desc->mothod(), desc));
                }
                //2. 查找（通过方法名查找，对应服务描述指针)
                ServiceDescribe::ptr select(const std::string &method_name){
                    std::unique_lock<std::mutex> lock(_mutex);
                    auto it = services.find(method_name);
                    if(it == services.end()){
                        return ServiceDescribe::ptr(); //返回空的指针
                    }
                    return it->second;
                }
                //3.删除
                void remove(const std::string &method_name){
                    std::unique_lock<std::mutex> lock(_mutex);
                    _services.erase(method_name);
                }
            
            private:
                std::mutex _mutex;                                                  //互斥锁
                std::unordered_map<std::string, ServiceDescribe::ptr> _services;    //管理"ServiceDescribe"对象,通过方法和服务描述对应
        };

        //Rpc路由功能
        class RpcRouter{
            public:
                using ptr = shared_ptr<RpcRouter>;
                RpcRouter():_service_manageer(std::make_shared<ServiceManager>()){}

                //注册（方法、回调函数）到Dispatcher模块：针对rpc请求进行回调处理的业务函数
                void onRpcRequest(const BaseConnection::ptr &conn, RpcRequest::ptr &request){
                    //1.查询客户端请求的方法描述：判断当前服务端能否提供对应的服务
                    //如果成功，返回该服务描述对象，进行处理
                    auto service = _service_manageer->select(request->method);
                    if(service.get() == nullptr){
                        ELOG("%s 服务未找到!", request->method().c_str());
                        return response(conn,request, Json::Value(), RCode::RCODE_NOT_FOUND_SERVICE);
                    }

                    //2.进行参数校验，确定能否提供服务
                    if(service->paramCheck(request->params()) == false){
                        ELOG("%s 服务参数校验失败！", request->method().c_str());
                        return response(conn, request, Json::Value(), RCode::RCODE_INVALID_PARAMS);  
                    }

                    //3.调用业务回调接口进行业务处理
                    Json::Value result;
                    bool ret = service->call(request->pragmas(), result);
                    if(ret == false){
                        ELOG("%s 服务参数校验失败！", request->method().c_str());
                        return response(conn, request, Json::Value(), RCode::RCODE_INTERNAL_ERROR);
                    }

                    //4.处理完毕得到结果，组织响应，向客户端发送
                    return resposne(conn, request, result, RCode::RCODE_OK);
                }

                //注册服务描述：插入服务描述
                void registerMethod(const ServiceDescribe::ptr &service){
                    return _service_manageer->insert(service);
                }
            private:              
                //RPC服务处理完结果，通过该函数进行处理发送信息(状态、方法变换)
                void response(const BaseConnection::ptr &conn,
                    const RpcRequest::ptr &req,
                    const Json::Value &res, rcode rcode){
                        auto msg = MassageFactory::create<RpcResponse>(); 
                        msg->setId(req->rid());
                        msg->setMType(req->method);
                        msg->setRCode(req->rcode);
                        msg->setResult(req->result);
                        conn->send(msg);
                    }

            private:
                ServiceManager:ptr _service_manageer;   //创建"ServiceManager"管理为成员对象。
        }
    }
}

//分层设计:
//ServiceDescribe: 关注单个服务的描述和行为
//ServiceManager: 关注服务的管理和查找
//RpcRouter: 关注请求的路由和响应
